home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fatted Calf
/
The Fatted Calf.iso
/
Applications
/
GraphicViewers
/
pCD
/
Source
/
Photo_CD.subproj
/
photoCD_Rdr.m
< prev
next >
Wrap
Text File
|
1993-03-27
|
10KB
|
395 lines
/*
* This class contains everything we know about the format of information
* on a Photo_CD. Note that this knowledge is not complete, it's just
* as much as has been deciphered by the hpcdtoppm program written by
* Hadmut Danisch (danisch@ira.uka.de). Some comments from that program:
* hpcdtoppm (Hadmut's pcdtoppm) v0.3
* Copyright (c) 1992 by Hadmut Danisch (danisch@ira.uka.de).
* Permission to use and distribute this software and its
* documentation for noncommercial use and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation. It is not allowed to sell this software in
* any way. This software is not public domain.
* Some of that program is reimplemented in this class, and the rest is
* still (currently) off in some C source and header files.
* These comments by:
* Garance Alistair Drosehn; Jan 14th, 1993
*/
#import "photoCD_Rdr.h"
#import "pcd.h"
#define PCD_READ_OK 0
#define PCD_READ_ERROR 1
#define PCD_READBUF { \
if ( READBUF < 1 ) { \
NXRunAlertPanel(0, \
" Unexpected eof while reading", \
0, 0, 0); \
} \
}
#define PCD_SEEK(x) { \
if (fseek(fin,((x) * SECSIZE),0)) { \
NXRunAlertPanel(0, \
" Unexpected error from fseek to sector %d", \
0, 0, 0, (x)); \
} \
}
extern void rotateBm( dim *w, dim *h, implane *r, implane *g, implane *b, enum TURNS t);
@implementation photoCD_Rdr
/* methods only called from within this class */
- (NXBitmapImageRep *) _allocBitmap
:(dim)width :(dim)height
red:(uBYTE *)redPlane
green:(uBYTE *)greenPlane
blue:(uBYTE *)bluePlane
{
u_char *rgb[5];
NXBitmapImageRep *bitmap;
rgb[0] = redPlane;
rgb[1] = greenPlane;
rgb[2] = bluePlane;
rgb[3] = NULL;
rgb[4] = NULL;
/* allocate the proper sized BitmapImage and use the planes
allocated by that for our processing */
bitmap = [[NXBitmapImageRep alloc] initDataPlanes:rgb
pixelsWide:width
pixelsHigh:height
bitsPerSample:8
samplesPerPixel:3
hasAlpha:NO
isPlanar:YES
colorSpace:NX_RGBColorSpace
bytesPerRow:0
bitsPerPixel:0];
if ( ! bitmap ) {
NXRunAlertPanel(0,
" Unable to allocate bitmap for a %d x %d image",
0, 0, 0, width, height);
/* probably should so something less drastic here */
exit(9);
}
return bitmap;
}
- (short)_getExpectedThumbnailCount
{
/* assume that the caller is reading an overview file */
struct ph0 *d;
PCD_SEEK(0);
PCD_READBUF;
d = (struct ph0 *) sbuffer;
return d->num_thumbs;
}
- setDoSharp:(BOOL)wantsDoSharp
{
mainSetSharpit( wantsDoSharp );
return self;
}
- setNextGammaCorrection:(BOOL)wantsNextCorr
{
if( wantsNextCorr) mainSetGammaCorr(C_NeXT);
else mainSetGammaCorr(C_LINEAR);
return self;
}
- (int)readOverviewFromFile:(char *)ovFil
curImageCount:(int)initialImageCount
ImageArray:(ovImageArray *)imageArrayPtr
MaxEntries:(int)overviewReadMax /* note: settable */
{
dim w, h;
implane Luma, Chroma1, Chroma2;
NXBitmapImageRep *bm;
int pictNumber, imageCount, expectedCount, readStatus;
char statStr[45];
fin=fopen(ovFil,"r");
if ( !fin ) {
NXRunAlertPanel(0,
" Unable to open overview file %s",
0, 0, 0, ovFil);
return -1;
}
/* free overview images from previous photo_cd (if any) */
for( ; initialImageCount > 0; initialImageCount-- ) {
bm = (*imageArrayPtr)[initialImageCount];
if ( bm != nil ) {
(*imageArrayPtr)[initialImageCount] = nil;
[bm free];
}
}
initialImageCount = imageCount = 0;
bm = nil;
expectedCount = [self _getExpectedThumbnailCount];
[readStatusField setStringValue:"Processing thumbnails"];
[readStatusPanel makeKeyAndOrderFront:self];
w=BaseW/4;
h=BaseH/4;
pictNumber = 1;
while ( (!feof(fin)) && (pictNumber <= overviewReadMax) ) {
/* Display a status message for each image, and call
* NXPing every 4 images to make sure the status messages
* are seen by the user. Without the call to NXPing, the
* messages are buffered up, and aren't displayed until
* that buffer is full.
*/
sprintf(statStr, "Reading Thumbnail # %d", pictNumber);
[readStatusField setStringValue:statStr];
if ( (pictNumber % 4) == 0 ) NXPing();
/* allocate the buffers */
planealloc(&Luma, w,h);
planealloc(&Chroma1, w,h);
planealloc(&Chroma2, w,h);
PCD_SEEK(5 + SeBase16 * (pictNumber - 1));
readStatus = readplain(w, h, &Luma, &Chroma1, &Chroma2, fin);
if (readStatus != PCD_READ_OK) {
if ( (readStatus == PCD_READ_ERROR)
&& ( imageCount == expectedCount) ) {
/* not a problem, no error message to write */
}
else {
/* more noticable error indication, as none of the
* other errors should ever happen.
*/
NXRunAlertPanel(0,
" Unexpected error (%d) from readplain in"
" readOverview processing for picture #%d"
" in file %s",
0, 0, 0, readStatus, pictNumber, ovFil);
}
break;
}
interpolate(&Chroma1);
interpolate(&Chroma2);
colconvert(&w,&h,&Luma,&Chroma1,&Chroma2);
/* at this point Luma is Red, Chroma1 is Green, Chroma2 is Blue */
bm = [self _allocBitmap :w :h
red:Luma.im green:Chroma1.im blue:Chroma2.im];
imageCount = pictNumber;
(*imageArrayPtr)[imageCount] = bm;
pictNumber++; /* try for next picture */
}
fclose(fin);
fin = 0x0;
if ( imageCount != expectedCount ) {
/* just a simple error message to console */
printf("Read in %d overview pictures, but %d were expected in %s\n",
imageCount, expectedCount, ovFil);
}
[readStatusPanel close];
return imageCount;
}
- readBitmapFromFile:(char *)imFile atSize:(enum is_Tags)imageSize
{
dim w, h, rp_w, rp_h;
int seekPos = -1, cd_offset = -1;
implane Luma, Chroma1, Chroma2;
NXBitmapImageRep *bm;
int readStatus;
enum TURNS turn=T_NONE;
fin=fopen(imFile,"r");
if ( !fin ) {
NXRunAlertPanel(0, " Unable to open image file %s",
0, 0, 0, imFile);
return nil;
}
switch ( imageSize ) {
case is_Base16_TAG:
w = rp_w = BaseW / 4;
h = rp_h = BaseH / 4;
seekPos = L_Head + 1;
break;
case is_Base4_TAG:
w = rp_w = BaseW / 2;
h = rp_h = BaseH / 2;
seekPos = L_Head + L_Base16 + 1;
break;
case is_4Base_TAG:
w = 2 * BaseW;
rp_w = BaseW;
h = 2 * BaseH;
rp_h = BaseH;
seekPos = L_Head + L_Base16 + L_Base4 + 1; // sic
break;
case is_16Base_TAG:
// this option does seem to work, but it's currently
// disabled in the preferences panel because it uses
// *huge* amounts of VM...
w = 4 * BaseW;
rp_w = BaseW;
h = 4 * BaseH;
rp_h = BaseH;
seekPos = L_Head + L_Base16 + L_Base4 + 1; // sic
break;
default:
// the correct values for case is_Base_TAG.
w = rp_w = BaseW;
h = rp_h = BaseH;
seekPos = L_Head + L_Base16 + L_Base4 + 1;
break;
}
/* allocate the buffers */
planealloc(&Luma, w,h);
planealloc(&Chroma1, w,h);
planealloc(&Chroma2, w,h);
PCD_SEEK(1); PCD_READBUF;
switch(sbuffer[0xe02 & 0x7ff]&0x03) {
case 0x00: turn=T_NONE; break;
case 0x01: turn=T_LEFT; break;
case 0x03: turn=T_RIGHT; break;
default:
NXRunAlertPanel(0,
" Unexpected “turn” in pickImage processing",
0, 0, 0);
fclose(fin); // perform some clean-up
fin = 0x0;
return nil; // can't process the picture
}
PCD_SEEK( seekPos );
readStatus = readplain(rp_w, rp_h, &Luma, &Chroma1, &Chroma2, fin);
if ( readStatus != PCD_READ_OK ) {
NXRunAlertPanel(0,
" Unexpected error (%d) from readplain in pickImage"
" processing for image at w=%d, h=%d",
0, 0, 0, readStatus, rp_w, rp_h);
fclose(fin); // perform some clean-up
fin = 0x0;
return nil; // can't process the picture
}
interpolate(&Chroma1);
interpolate(&Chroma2);
if ( w != rp_w ) { // ie, is_4Base_TAG or is_16Base_TAG
// these image sizes need more interpolate-tion calls
interpolate(&Luma);
interpolate(&Chroma1);
interpolate(&Chroma2);
// They also need this readhqt/decode processing.
#define nullplane ((implane *) 0)
switch ( imageSize ) {
case is_4Base_TAG:
cd_offset = L_Head + L_Base16 + L_Base4 + L_Base;
PCD_SEEK(cd_offset + 4);
readhqt(w, h, 1, fin);
PCD_SEEK(cd_offset + 5);
decode(w, h, &Luma, nullplane, nullplane, 0, fin);
break;
case is_16Base_TAG:
cd_offset = L_Head + L_Base16 + L_Base4 + L_Base;
PCD_SEEK(cd_offset + 4);
readhqt(w / 2, h / 2, 1, fin);
PCD_SEEK(cd_offset + 5);
decode(w / 2, h / 2, &Luma, nullplane, nullplane, 0, fin);
interpolate(&Luma);
cd_offset = ftell(fin);
if (cd_offset % SECSIZE) {
NXRunAlertPanel(0,
" Base16 Position error in pickImage",
0, 0, 0);
fclose(fin); // perform some clean-up
fin = 0x0;
return nil; // can't process the picture
}
cd_offset /= SECSIZE;
PCD_SEEK(cd_offset + 12);
readhqt(w, h, 3, fin);
PCD_SEEK(cd_offset + 14);
decode(w, h, &Luma, &Chroma1, &Chroma2, 0, fin);
interpolate(&Chroma1);
interpolate(&Chroma2);
break;
default:
NXRunAlertPanel(0, " Internal error in pickImage",
0, 0, 0);
fclose(fin); // perform some clean-up
fin = 0x0;
return nil; // can't process the picture
}
#undef nullplane
}
colconvert(&w,&h,&Luma,&Chroma1,&Chroma2);
/* at this point Luma is Red, Chroma1 is Green, Chroma2 is Blue */
if( turn != T_NONE ) {
rotateBm(&w, &h, &Luma, &Chroma1, &Chroma2, turn);
}
bm = [self _allocBitmap :w :h
red:Luma.im green:Chroma1.im blue:Chroma2.im];
fclose(fin);
fin = 0x0;
/* note that anyone freeing this bitmap will also have to know
to free the RGB buffers that it's using */
return bm;
}
/* note that nobody calls this yet, instead there's code that's
mighty similar to this over in PhotoWinProcs. Oops.
*/
- freeDataPlanes:(NXBitmapImageRep *)imgBitmap
{
u_char *rgb[5];
if ( [imgBitmap isPlanar] ) {
/* a rather sleezy way to distinguish between images that
were read in and images which were cut/pasted in... */
[imgBitmap getDataPlanes:rgb];
if ( rgb[0] ) free( rgb[0] );
if ( rgb[1] ) free( rgb[1] );
if ( rgb[2] ) free( rgb[2] );
}
return self;
}
@end